package com.geek.framework.study.config.microprofile;

import com.geek.framework.study.config.microprofile.converter.StringConversionService;
import com.geek.framework.study.config.microprofile.value.DefaultValue;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigValue;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.eclipse.microprofile.config.spi.Converter;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;

import static java.util.stream.StreamSupport.stream;


public class DefaultConfig  implements Config {

    private final ConfigSources configSources;

    private final StringConversionService conversionService;

    public DefaultConfig(ConfigSources configSources, StringConversionService conversionService) {
        this.configSources = configSources;
        this.conversionService = Optional.ofNullable(conversionService).orElse(StringConversionService.getSharedInstance());
    }



    @Override
    public <T> T getValue(String s, Class<T> aClass) {
        ConfigValue configValue = getConfigValue(s);
        if (configValue == null) {
            return null;
        }
        if (conversionService.canConvert(configValue.getValue(), aClass)) {
            return conversionService.convert(configValue.getValue(), aClass);
        }
        throw new UnsupportedOperationException("不支持这种转化形式");
    }

    @Override
    public ConfigValue getConfigValue(String key) {
        Iterator<ConfigSource> iterator = configSources.iterator();
        while (iterator.hasNext()) {
            ConfigSource next = iterator.next();
            String value = next.getValue(key);
            if (value != null) {
                return new DefaultValue(key, value, value, next.getName(), next.getOrdinal());
            }
        }
        return null;
    }

    @Override
    public <T> Optional<T> getOptionalValue(String s, Class<T> aClass) {
        T value = getValue(s, aClass);
        return Optional.ofNullable(value);
    }

    @Override
    public Iterable<String> getPropertyNames() {
        return stream(configSources.spliterator(), false)
                .map(ConfigSource::getPropertyNames)
                .collect(LinkedHashSet::new, Set::addAll, Set::addAll);
    }

    @Override
    public Iterable<ConfigSource> getConfigSources() {
        return configSources;
    }

    @Override
    public <T> Optional<Converter<T>> getConverter(Class<T> aClass) {
        return Optional.empty();
    }

    @Override
    public <T> T unwrap(Class<T> aClass) {
        return null;
    }
}
